package directory

import (
	"errors"
	"fmt"
	"gitee.com/ttdevcn/gio/file"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"slices"
	"strings"
	"time"
)

// Delete 文件夹/文件通用删除方法
func Delete(path string) error {
	err := os.RemoveAll(path)
	if err != nil {
		if strings.Index(err.Error(), "Access is denied") != -1 {
			err = GetPerm(path)
			if err != nil {
				return err
			}
			return os.RemoveAll(path)
		}

	}
	return nil
}

// GetPerm 获取win管理员(admin)权限
func GetPerm(path string) error {
	cmd := exec.Command("takeown", "/f", path, "/r", "/d", "y")
	_, err := cmd.CombinedOutput()
	time.Sleep(300)
	if err != nil {

		return err
	}
	// icacls命令，赋予Administrators完全控制权限
	cmd2 := exec.Command("icacls", path, "/grant", "Administrators:F", "/T")

	// 执行命令
	_, err = cmd2.CombinedOutput()
	time.Sleep(300)
	if err != nil {
		return err
	}
	return nil
}

type Directory struct {
	Path string
	Name string
	//Children []Directory
	//Files    []File
}

// GetFilesAll 获取文件夹中的文件(包含子文件夹)
func (d *Directory) GetFilesAll() []file.File {
	return nil
}

// GetChildrenDirs 获取子文件夹
func (d *Directory) GetChildrenDirs() []Directory {

	var dirs []Directory

	// 读取目录内容
	files, err := os.ReadDir(d.Path)
	if err != nil {
		fmt.Println("Error:", err)
		return nil
	}
	// 遍历第一层子目录
	for _, f := range files {
		if f.IsDir() {
			//fmt.Println("Dir:", file.Name())
			dirs = append(dirs, Directory{Path: d.Path + string(os.PathSeparator) + f.Name(), Name: f.Name()})
		}
		//else {
		//	fmt.Println("File:", file.Name())
		//}
	}
	if len(dirs) == 0 {
		return nil
	}
	return dirs

}

// CopyFile 使用io.Copy进行文件的复制，同时也会复制文件的所有权限
// @param src 复制文件
// @param des 目标文件
// @return error 错误信息
func CopyFile(src, des string) error {
	// 判断文件是否存在
	if !IsExist(src) {
		return errors.New("要复制的文件不存在")
	}

	// 打开文件
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer func(srcFile *os.File) {
		err := srcFile.Close()
		if err != nil {

		}
	}(srcFile)

	// 获取源文件的权限
	fi, _ := srcFile.Stat()
	perm := fi.Mode()

	// 创建目标文件，并复制源文件的所有权限
	desFile, err := os.OpenFile(des, os.O_RDWR|os.O_CREATE|os.O_TRUNC, perm)
	if err != nil {
		return err
	}
	defer func() {
		_ = desFile.Close()
	}()

	// 进行复制
	_, err = io.Copy(desFile, srcFile)

	// 返回
	return err
}

func moveDir(sourceDir string, targetDir string) error {
	dirpath := filepath.Dir(targetDir)
	if !IsExist(dirpath) {

		err := CreateDir(dirpath)
		if err != nil {
			return err
		}
	}

	fs, err := os.ReadDir(sourceDir)
	if err == nil {
		//遍历当前文件夹
		for _, f := range fs {
			//判断是否是文件夹
			if f.IsDir() {
				err = moveDir(sourceDir+string(os.PathSeparator)+f.Name(), targetDir+string(os.PathSeparator)+f.Name())
				if err != nil {
					return err
				}
			} else {
				//判断到是文件

				//创建文件夹
				_ = os.Mkdir(targetDir, os.ModePerm)
				//使用重命名方法移动文件
				err := CopyFile(sourceDir+string(os.PathSeparator)+f.Name(), targetDir+string(os.PathSeparator)+f.Name())
				if err != nil {
					return err
				}
				err = os.Remove(sourceDir + string(os.PathSeparator) + f.Name())
				return err
			}
		}
	}
	//fs2, err := os.ReadDir(sourceDir)
	//if err == nil {
	//	if len(fs2) == 0 {
	//		_ = os.Remove(sourceDir)
	//	}
	//} else {
	//	return err
	//}
	return nil
}
func copyDir(sourceDir string, targetDir string) error {

	dirpath := filepath.Dir(targetDir)
	if !IsExist(dirpath) {

		err := CreateDir(dirpath)
		if err != nil {
			return err
		}
	}

	fs, err := os.ReadDir(sourceDir)
	if err == nil {
		//遍历当前文件夹
		for _, f := range fs {
			//判断是否是文件夹
			if f.IsDir() {
				err = copyDir(sourceDir+string(os.PathSeparator)+f.Name(), targetDir+string(os.PathSeparator)+f.Name())
				if err != nil {
					return err
				}
			} else {
				//判断到是文件

				//创建文件夹

				err := CreateDir(targetDir)
				if err != nil {
					return err
				}
				//使用重命名方法移动文件
				err = CopyFile(sourceDir+string(os.PathSeparator)+f.Name(), targetDir+string(os.PathSeparator)+f.Name())
				if err != nil {
					return err
				}
			}
		}
	}
	return nil
}

// Move 移动文件夹
func (d *Directory) Move(targetDir string) error {

	err := moveDir(d.Path, targetDir)
	return err
}

// Copy 复制文件夹
func (d *Directory) Copy(targetDir string) error {

	err := copyDir(d.Path, targetDir)
	return err
}

//func DeleteDirAll(path string) error {
//	fs, err := os.ReadDir(path)
//	if err == nil {
//		//遍历当前文件夹
//		for _, f := range fs {
//			//判断是否是文件夹
//			if f.IsDir() {
//				_ = DeleteDirAll(path + string(os.PathSeparator) + f.Name())
//			} else {
//				//删除文件
//				_ = os.Remove(path + string(os.PathSeparator) + f.Name())
//
//			}
//		}
//	}
//	_ = os.Remove(path)
//	if !IsExist(path) {
//		return nil
//	} else {
//		return errors.New("无法删除该文件夹")
//	}
//
//}

// Delete  删除当前文件夹的所有内容
func (d *Directory) Delete() error {

	return Delete(d.Path)

}

// Rename 重命名文件夹
func (d *Directory) Rename(newName string) error {
	return os.Rename(d.Path, filepath.Dir(d.Path)+string(os.PathSeparator)+newName)
}

// GetParent 获取父级文件夹路径
func (d *Directory) GetParent() *Directory {

	sp := slices.DeleteFunc(strings.Split(d.Path, string(os.PathSeparator)), func(s string) bool {
		return s == ""
	})
	var tpath string
	for i, v := range sp {

		if i < len(sp)-1 {
			if i == 0 {
				tpath += v

			} else {
				tpath += string(os.PathSeparator) + v
			}
		}
	}
	return OpenDir(tpath)
}

// GetFile 通过文件名获取文件
func (d *Directory) GetFile(name string) ([]*file.File, error) {

	return nil, nil
}

// GetDir 通过文件夹名获取文件夹
func (d *Directory) GetDir(name string) ([]*Directory, error) {

	return nil, nil
}

// GetALLDir 获取当前目录所有的子文件夹
func (d *Directory) GetALLDir() []*Directory {

	var dirs []*Directory
	fs, err := os.ReadDir(d.Path)
	if err == nil {
		//遍历当前文件夹
		for _, f := range fs {
			//判断是否是文件夹
			if f.IsDir() {
				dirs = append(dirs, OpenDir(d.Path+string(os.PathSeparator)+f.Name()))
			}
		}
	}
	return dirs
}

func getallfile(path string) []*file.File {
	var files []*file.File
	fs, err := os.ReadDir(path)
	if err == nil {
		//遍历当前文件夹
		for _, f := range fs {
			//判断是否是文件夹
			if f.IsDir() {
				tfs := getallfile(path + string(os.PathSeparator) + f.Name())
				for _, v := range tfs {
					files = append(files, v)
				}
			} else {
				tf, _ := file.OpenFile(path + string(os.PathSeparator) + f.Name())
				if tf != nil {
					files = append(files, tf)
				}
			}
		}
	}
	return files
}

// GetAllFile 获取当前目录所有的子文件夹
func (d *Directory) GetAllFile(isSearchSubDir bool) []*file.File {
	if isSearchSubDir {
		return getallfile(d.Path)

	} else {
		var files []*file.File
		fs, err := os.ReadDir(d.Path)
		if err == nil {
			//遍历当前文件夹
			for _, f := range fs {
				//判断是否是文件夹
				if !f.IsDir() {
					tf, _ := file.OpenFile(d.Path + string(os.PathSeparator) + f.Name())
					if tf != nil {
						files = append(files, tf)
					}
				}
			}
		}
		return files
	}

}

// OpenDir 打开文件夹
func OpenDir(path string) *Directory {

	d := Directory{Path: path, Name: filepath.Base(path)}

	return &d
}

//// IsExistDir 判断文件夹是否存在
//func IsExistDir(path string) bool {
//
//	return false
//}

// IsExist 判断是否存在
func IsExist(path string) bool {
	existed := true
	if _, err := os.Stat(path); os.IsNotExist(err) {
		existed = false
	}
	return existed

}

// IsExist 判断是否存在
func (d *Directory) IsExist() bool {
	existed := true
	if _, err := os.Stat(d.Path); os.IsNotExist(err) {
		existed = false
	}
	return existed

}

// CreateDir 创建文件夹
func CreateDir(dirpath string) error {
	//os.PathSeparator

	sp := slices.DeleteFunc(strings.Split(dirpath, string(os.PathSeparator)), func(s string) bool {
		return s == ""
	})
	var tpath string
	for i, v := range sp {

		if i == 0 {
			tpath += v
			if !IsExist(v) {
				return errors.New("不存在\"" + v + "\"路径")
			}
		} else {
			tpath += string(os.PathSeparator) + v
			if !IsExist(tpath) {

				err := os.Mkdir(tpath, os.ModePerm)
				if err != nil {
					// 如果文件夹已存在，也可以选择忽略错误
					if !os.IsExist(err) {
						return nil
					}
					return err
				}

			}

		}

	}
	return nil
}
